home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
jpeg.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
14KB
|
508 lines
/*
* $Id: jpeg.c,v 0.91 1994/02/20 00:52:49 zhao Pre-Release $
*
*. This file is part of BIT shareware package. After the two weeks of
* free evaluation period, you are encouraged (required) to register
* your copy for a small registration fee, which is $35 for personal use
* and $50 for commercial, government and institutional use.
*
* Copyright(c) 1993, 1994 by T.C. Zhao.
* All rights reserved.
*
* Permission to use, copy, and distribute this software in its entirety
* for non-commercial purposes is hereby granted, provided that the
* above shareware and copyright notices and this permission notice
* appear in all copies and their documentation.
*
* This software may be modified for your own use, but modified versions
* may not be distributed without prior consent of the author.
*
* This software is provided "as is" without expressed or implied
* warranty of any kind.
*
*.
*
* JPEG(JFIF) related routines are based in part on the work of
* the Independent JPEG Group. Also uses the Independent JPEG Group's
* library. See related files in jpeg directory for more details.
*/
#ifndef NO_JPEG
#if !defined(lint) && defined(F_ID)
char *id_jpg = "$Id: jpeg.c,v 0.91 1994/02/20 00:52:49 zhao Pre-Release $";
#endif
#include "bit.h"
#include <stdlib.h> /* exit prototype */
#include "jinclude.h"
/* const may or may not be defined to be empty by jinclude.h */
#ifdef Const
#undef const
#endif
#include <setjmp.h>
/******** Decompression parameters: always output RGB *************/
static int jpg_quant = 0; /* set to # of colors */
static int jpg_blksm = 0; /* block smoothing */
/******* compression parameters: all used **************************/
static int jpeg_qval = 75; /* default Q-value */
static int jpeg_sval = 0; /* default smoothing factor */
static int jpeg_opt = 0; /* optimize */
/******** some bit control parameters *********************************/
static int sofar, isjwrite; /* line read and io id */
static jmp_buf jpg_jmp; /* error recoveraty jump buffer */
static IPTR jpg_current; /* local copy of image pointer */
static long jpg_rlines; /* reporting control */
static int read_JPEG_file(FILE *);
static int write_JPEG_file(FILE *);
/*******************************************************************
* One liner summary of JPEG output options
******************************************************************/
/* ARGSUSED */
const char *
JPEG1_wdefault(const IPTR ip)
{
static char rep[30];
sprintf(rep, "Q=%d Smooth=%d", jpeg_qval, jpeg_sval);
return rep;
}
/*****************************************************************
* Solicit output options
****************************************************************/
/* ARGSUSED */
int
JPEG1dump_init(IPTR im)
{
(void) get2int("Q value", &jpeg_qval, 5, 100,
"Smooth", &jpeg_sval, 0, 100,
"Optimize", &jpeg_opt, HELP_JPEG, 0);
return 0;
}
/*********************************************************************
* The entry point for writing
*********************************************************************/
int
JPEG1_dump(IPTR img)
{
sofar = 0;
jpg_current = img;
isjwrite = 1;
return write_JPEG_file(img->fp);
}
/*
* the use of the canned library sort of breaks down the systematic approach
* of the BIT program as both the BIT program and the library want to take
* control. Have to fake description because we do not want to know too many
* details of the file format, the consequence of this is that the loading
* routine will have to do the memoery allocation explicitly.
*/
int
JPEG1_desc(IPTR im)
{
/* fake the size to 1X1 to signal info reporting func */
jpg_current = im;
jpg_current->w = 1;
jpg_current->h = 1;
jpg_current->esize = 4;
jpg_current->type = T_RGBA;
return 0;
}
int
JPEG1_load(IPTR im)
{
if (jpg_current != im)
{
Bark("JpegLoad", "Internal error");
return -1;
}
isjwrite = sofar = 0;
if (read_JPEG_file(im->fp) < 0)
return -1;
if (im->type != T_GRAY)
im->type = T_RGBA;
return sofar;
}
static external_methods_ptr emethods;
METHODDEF void
trace_message(const char *msgtext)
{
/*
* error messages may have in it the file name, which could be
* MAXDLEN+MAXFLEN long. Really wish there were something line an
* snprintf
*/
char errmsg[MAXFLEN + MAXDLEN], *p;
const char *func = isjwrite ? "JPG_write" : "JPG_read";
/* wish there were an snprintf */
sprintf(errmsg, msgtext,
emethods->message_parm[0], emethods->message_parm[1],
emethods->message_parm[2], emethods->message_parm[3],
emethods->message_parm[4], emethods->message_parm[5],
emethods->message_parm[6], emethods->message_parm[7]);
/* break long lines (otherwise clipped by GL) */
if (strlen(errmsg) < 40)
{
Bark(func, "%s:%s", jpg_current->ifile, errmsg);
}
else
{ /* break it at space */
if ((p = strchr(errmsg + 15, ' ')))
*p = '\n';
Bark(func, "%s:%s", jpg_current->ifile, errmsg);
}
}
/* really do not what to exit, rather transfer control to main driver */
METHODDEF void
error_exit(const char *msgtext)
{
trace_message(msgtext); /* report the error message */
(*emethods->free_all) (); /* clean up memory allocation & temp files */
longjmp(jpg_jmp, 1); /* return control to outer routine */
}
METHODDEF void
output_init(decompress_info_ptr info)
{
jpg_current->w = info->image_width;
jpg_current->h = info->image_height;
jpg_rlines = progress_report("Loading JPEG ...", jpg_current->h);
if (info->out_color_space == CS_GRAYSCALE)
jpg_current->type = T_GRAY;
else if (info->out_color_space == CS_RGB)
jpg_current->type = T_RGBA;
else
{ /* unecessary unless the driver screwed-up */
Bark("JPG_load", "%s: Bad Colorspace", jpg_current->ifile);
}
/* always converts to RGB by load */
update_image_info(jpg_current);
if (img_get_rastermem(jpg_current) < 0)
longjmp(jpg_jmp, 1);
}
METHODDEF void
put_pixel_rows(decompress_info_ptr info, int num_rows,
JSAMPIMAGE pixel_data)
{
register rgba_t *rgba;
register JSAMPROW ptr0, ptr1, ptr2, ptr;
register int row;
register int width = info->image_width;
register int height = info->image_height;
#ifdef V4A
/*
* it would appear that V4a's code might produce more scanlines than they
* are. Check here
*/
if ((num_rows + sofar) > height)
{
num_rows = height - sofar;
M_warn("OutputRows", "sofar=%d height=%d num_rows=%d\n",
sofar, height, num_rows);
}
#endif
if (info->out_color_space == CS_RGB)
{
for (row = 0; row < num_rows; row++, sofar++)
{
rgba = ((rgba_t **) jpg_current->mraster)[height - 1 - sofar];
ptr0 = pixel_data[0][row];
ptr1 = pixel_data[1][row];
ptr2 = pixel_data[2][row];
ptr = ptr0 + width;
for (; ptr0 < ptr; ptr0++, ptr1++, ptr2++)
{
*rgba++ = Pack(*ptr0, *ptr1, *ptr2);
}
REPORT(sofar, jpg_rlines);
}
}
else if (info->out_color_space == CS_GRAYSCALE)
{
for (row = 0; row < num_rows; row++, sofar++)
{
rgba = ((rgba_t **) jpg_current->mraster)[height - 1 - sofar];
ptr0 = ptr = pixel_data[0][row];
for (ptr = ptr0 + width; ptr0 < ptr; ptr0++)
{
*rgba++ = Pack(*ptr0, *ptr0, *ptr0);
}
REPORT(sofar, jpg_rlines);
}
}
}
/*
* color map is ready assigned in put_color_map
*/
/* ARGSUSED */
METHODDEF void
put_cmap_rows(decompress_info_ptr info, int num_rows,
JSAMPIMAGE pixel_data)
{
register rgba_t *rgba, *rs, *mrgb = jpg_current->cmap->p_h.rgba;
register JSAMPROW ptr;
register int row;
register int width = jpg_current->w, height = jpg_current->h;
for (row = 0; row < num_rows; row++, sofar++)
{
ptr = pixel_data[0][row];
rgba = ((rgba_t **) jpg_current->mraster)[height - 1 - sofar];
for (rs = rgba + width; rgba < rs;)
{
*rgba++ = mrgb[*ptr++];
}
REPORT(sofar, jpg_rlines);
}
}
METHODDEF void
put_color_map(decompress_info_ptr info, int num_colors,
JSAMPARRAY cm)
{
int i, j;
jpg_current->type = T_CMAP;
jpg_current->cmap->colors = num_colors;
for (j = 0; j < info->color_out_comps; j++)
{
for (i = 0; i < num_colors; i++)
{
jpg_current->cmap->ct[j][i] = cm[j][i];
}
}
info->methods->put_pixel_rows = put_cmap_rows;;
if (info->color_out_comps == 1)
{ /* grap scale */
for (i = 0; i < num_colors; i++)
jpg_current->cmap->p_h.rgba[i] = Pack(cm[0][i], cm[0][i], cm[0][i]);
jpg_current->cmap->packed = 1;
}
else if (info->color_out_comps == 3)
{
pack_cmap(jpg_current->cmap);
}
else
{
Bark("JPG_load", "%s: BadColorComponent", jpg_current->ifile);
longjmp(jpg_jmp, 1);
}
}
/* ARGSUSED */
METHODDEF void
output_term(decompress_info_ptr info)
{
remove_progress_report();
}
METHODDEF void
d_ui_method_selection(decompress_info_ptr info)
{
if (info->jpeg_color_space == CS_GRAYSCALE)
info->out_color_space = CS_GRAYSCALE;
info->methods->output_init = output_init;
info->methods->put_color_map = put_color_map;
info->methods->put_pixel_rows = put_pixel_rows;
info->methods->output_term = output_term;
}
static int
read_JPEG_file(FILE * fp)
{
static struct Decompress_info_struct dcinfo;
static struct Decompress_methods_struct dc_methods;
static struct External_methods_struct e_methods;
dcinfo.input_file = fp;
dcinfo.output_file = NULL; /* if no actual output file involved */
dcinfo.methods = &dc_methods; /* links to method structs */
dcinfo.emethods = &e_methods;
emethods = &e_methods; /* save struct addr for possible access */
e_methods.trace_message = trace_message;
e_methods.error_exit = error_exit; /* supply error-exit routine */
e_methods.trace_level = 0;
e_methods.num_warnings = 0;
e_methods.first_warning_level = 0;
e_methods.more_warning_level = 3;
if (setjmp(jpg_jmp))
{
remove_progress_report();
return sofar;
}
jselmemmgr(&e_methods); /* select std memory allocation routines */
dc_methods.d_ui_method_selection = d_ui_method_selection;
dcinfo.desired_number_of_colors = jpg_quant;
/* quantize only if sensible number of color is requested */
dcinfo.quantize_colors = jpg_quant > 10;
dcinfo.do_block_smoothing = jpg_blksm;
j_d_defaults(&dcinfo, TRUE);
jselrjfif(&dcinfo);
#ifdef MTRACE
M_trace("ReadJpeg", "Right before decompress");
#endif
jpeg_decompress(&dcinfo);
return sofar;
}
/*
* compressing routines
*/
METHODDEF void
input_init(compress_info_ptr info)
{
info->image_width = jpg_current->w;
info->image_height = jpg_current->h;
if (jpg_current->type == T_GRAY)
{
info->input_components = 1;
info->in_color_space = CS_GRAYSCALE;
}
else
{
info->in_color_space = CS_RGB;
info->input_components = 3;
}
info->data_precision = PCBITS; /* bits per pixel component value */
jpg_rlines = progress_report("Writing JPEG ...", jpg_current->h);
}
METHODDEF void
get_input_row(compress_info_ptr info, JSAMPARRAY pixel_row)
{
register JSAMPROW ptr0, ptr1, ptr2;
register int col, r, g, b;
register rgba_t *rgba, *rend;
rgba = ((rgba_t **) jpg_current->mraster)[jpg_current->h - 1 - sofar];
if (jpg_current->type == T_RGBA)
{
ptr0 = pixel_row[0];
ptr1 = pixel_row[1];
ptr2 = pixel_row[2];
for (rend = rgba + info->image_width; rgba < rend; rgba++)
{
Unpack(*rgba, r, g, b);
*ptr0++ = (JSAMPLE) r;
*ptr1++ = (JSAMPLE) g;
*ptr2++ = (JSAMPLE) b;
}
REPORT(sofar, jpg_rlines);
sofar++;
}
else if (jpg_current->type == T_GRAY)
{
ptr0 = pixel_row[0];
for (col = 0; col < info->image_width; col++)
{
r = (*rgba & 0xff);
*ptr0++ = (JSAMPLE) r;
rgba++;
}
REPORT(sofar, jpg_rlines);
sofar++;
}
}
/* ARGSUSED */
METHODDEF void
input_term(compress_info_ptr info)
{
remove_progress_report();
}
METHODDEF void
c_ui_method_selection(compress_info_ptr info)
{
if (info->in_color_space == CS_GRAYSCALE)
j_monochrome_default(info);
jselwjfif(info);
}
static int
write_JPEG_file(FILE * fp)
{
static struct Compress_info_struct cinfo;
static struct Compress_methods_struct c_methods;
static struct External_methods_struct e_methods;
cinfo.emethods = &e_methods;
cinfo.methods = &c_methods; /* links to method structs */
emethods = &e_methods; /* save struct addr for possible access */
e_methods.error_exit = error_exit; /* supply error-exit routine */
e_methods.trace_message = trace_message;
jselmemmgr(&e_methods); /* select std memory allocation routines */
c_methods.input_init = input_init;
if (setjmp(jpg_jmp))
{
remove_progress_report();
fclose(cinfo.output_file);
return sofar;
}
c_methods.get_input_row = get_input_row;
c_methods.input_term = input_term;
c_methods.c_ui_method_selection = c_ui_method_selection;
cinfo.input_file = NULL; /* if no actual input file involved */
cinfo.output_file = fp;
/* permitted compression options */
j_c_defaults(&cinfo, jpeg_qval, FALSE);
cinfo.smoothing_factor = jpeg_sval;
cinfo.optimize_coding = jpeg_opt;
#ifdef MTRACE
M_trace("ReadJpeg", "Right before compress");
#endif
jpeg_compress(&cinfo);
fflush(cinfo.output_file);
return sofar;
}
#endif